ここで非常に簡単にではありますが、Flex と Lex の両方を概観してみます。Flex、Lex それぞれの性能と Lex のようなユーティリティに対する POSIX 標準への準拠度についてもいくつか一般的なコメントを示します。
Flex は Lex のより優れた再実装であり、Lex と同様、パターンとアクションの記述情報を入力として受け取って、それらのパターンにマッチする能力を持つ C のスキャナに変換するものです。しかしながら、Flex はより少ない時間でテーブルを生成しますし、Flex により生成されるテーブルは Lex により生成されるテーブルと比較してはるかに効率的なものです(Flex が正確には何を生成するのかに関する説明については、このマニュアルの冒頭で言及した書籍を参照してください)。
Flex は Lex および POSIX と十分に互換性があり、それ独自の特別な機能もいくつか追加しています。
Flex は大体のところ Lex および POSIX の両方と互換性があります。将来は(Flex、POSIX
のいずれかが変わることによって)さらに POSIX との互換性を高めていくでしょう。しかし、Flex、Lex、POSIX
には異なる部分もいくつかあります。それを以下に示します。
排他的スタート状態 | Flex、POSIX は排他的スタート状態をサポートしていますが、Lex はサポートしていません。
|
定義 | Lex と Flex では定義の展開の方法が違います。Flex(および POSIX のドラフト仕様)は、定義を展開するときに丸括弧
() で囲いますが、Lex は囲いません。このことは Flex 定義では演算子 ^、$、/、<<EOF>>、<スタート状態>
は使うことができないということを意味しています。
これがもたらす主要な問題の1つに、マッチの優先順位に影響を与え、Flex
と Lex の間でスキャン処理に微妙な相違が出てくるということがあります。この問題の例については、***ページの
3.6 節「パターン・セクション」を参照してください。
|
input() | Flex および POSIX のドラフト仕様では input() は再定義可能ではありません。入力を制御するのに
input() を再定義する代わりに、Flex では YY_INPUT という拡張機能を使います(これは現在のところ
POSIX ではサポートされていません)。また、Lex とは異なり、Flex の input()
は yytext の値を変更するという点に注意してください。
|
output() | Flex は output() ルーチンをサポートしていません。ECHO の出力は yyout
経由で行われます。この yyout のデフォルトは stdout です。これを使うように
output() を書くことも可能ですが、現在の POSIX のドラフト仕様は output()
が正確には何をすべきなのかを示していません。
|
ラトフォ・スキャナ(ratfor scanner) | Flex、POSIX のどちらも Lex のラトフォ・スキャナ(ratfor scanner)・オプション(%r)をサポートしていません。
|
yylineno | これは Flex、POSIX にはない Lex のドキュメント化されていない機能です。しかし、Flex
で行数をカウントする機能を実装するのは難しくありません。定義中に行数カウント機能を組み込む方法の例については、***ページの
9.5 節「その他」を参照してください。
|
yywrap() | 現在のところ yywrap() はマクロです。POSIX のドラフト仕様では、これは関数であるべきとされていますので、おそらく将来は変更されることになるでしょう。
|
unput() | 現在のところ unput() は yytext と yyleng の値を破壊しますが、次のトークンがマッチされるまではこのようなことは不当です。Lex
と POSIX では yytext と yyleng は unput() によって影響されません。
|
数値範囲 | POSIX によると、abc{1,3} は「ab のうしろに1個、2個、または3個の
c が続くもの」にマッチすべきとなっています。Flex はこのとおりに動きますが、Lex
はこれを「1個、2個、または3個の abc」と解釈します。
|
yytext | Flex において yytext の正しい定義は extern char *yytext ですが、Lex
では extern char yytext[] です。配列によるアクセス方法は性能にかなりの影響を及ぼすので、Flex
では extern char *yytext を使い続けるでしょう。
最新の POSIX ドラフト仕様は、%array と %pointer を導入することによって、両方の方法をサポートしています。これは
Flex と Lex のいずれにもまだ組み込まれていません。
|
テーブル・サイズ | Lex にはテーブル・サイズ宣言子( %p、%a 等)がありますが、Flex ではこれらは必要ありません。互換性のために、これらは認識はされますが、ただ無視されるだけです。
|
FLEX_SCANNER | スキャナが Flex と Lex のどちらにより生成されたかによってコードをインクルードしたりしなかったりすることができるように、FLEX_SCANNER
が #define によって定義されています。
|
アクション | Flex では、大括弧の対 {...} を使うことなく単一行において複数の文を置くことができます。これに対して
Lex は、そのような行を単一文に切り詰めてしまいます。
|
コメント | Flex ではコメントを # で始めることができますが、Lex と POSIX ではできません。ただし、この形式のコメントを使うことはお勧めできません。
|
yyterminate()、yyrestart()、<<EOF>>、YY_DECL、#line 指示子 | これらはいずれも Lex ではサポートされていませんし、POSIX において明示的に定義されてもいません。#line
指示子の説明に関しては***ページの 10.1 節「Flex
コマンドライン・オプションの要約」を参照してください。
|
Lex はスキャナを作成するための標準的な UNIX ユーティリティであり、長い歴史を持っています。Lex は Flex と非常によく似ていますが、スキャナを生成するのにより多くの時間がかかりますし、Lex の生成するスキャナは Flex の生成するスキャナよりも通常は遅いものです。Lex は、特に多くの POSIX 機能を提供していないという理由から、置き換える必要が大いにあります。これらの POSIX 機能を Flex は提供しています。より多くのコンピュータ・システムが POSIX 互換になるにつれて Flex の提供する多くの機能をサポートしなければならなくなり、このためにおそらくは Flex が Lex の代わりにインストールされるようになるでしょう(例えば、4.4 BSD リリースは Flex を使うことになります)。しかし、Lex がインストールされている少数のシステムがあるために、しばらくの間は Lex の存在は確実に維持されるでしょう。
Flex と Lex の大きな違いは、Flex が性能を考慮して書かれたという点にあります。一般的には、Flex を持っているのであればそれを使うべきです。両者の性能差は無視するにはあまりにも大きすぎます。しかし、移植性が主要な重要性を持つのであれば、スキャナ定義は可能な限り Lex のものに近づけるべきです。というのは Lex は事実上すべての UNIX マシンに入っていることが保証されていますが、Flex は入っていない可能性があるからです(しかし、Flex のインストールは通常は取るに足りない作業です)。このような場合に残念なのは、Flex と POSIX が持っている排他的スタート状態のようなより便利な拡張機能を使うことができなくなるということです。
この問題を回避するためのもう1つの方法は Flex でスキャナを作成して、作成されたスキャナを配布することです。スキャナというものは一度書かれるとほとんど変更されることがないので、これは実行可能なオプションであることが多いのです。仮に変更が必要になったとしても、プログラムの他の部分も相当変更しなければならない可能性があり、よってプログラムを更新するための努力全体から見れば、Flex をインストールすることなどはほんの些細なものでしょう。
Copyright (C) 1992, 1993 Free Software Foundation
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the Free Software Foundation.
日本語訳:市川和久
Japanese translation by Kazuhisa Ichikawa (ki@home.email.ne.jp)